package org.krivtsun.scanlab.utils;

import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageReaderSpi;
import javax.swing.filechooser.FileFilter;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * todo Add "Common Image files" format
 * todo Remove RAW file format ???
 *
 * @author Andrew Krivtsun
 */
public class FileTypeFilters {

    private static FileFilter[] filters;

    // from ImageReader#getFormatName()
    private static String getFormatName(ImageReaderSpi spi) throws IOException {
        //return spi.getFormatNames()[0].toUpperCase();
        return spi.createReaderInstance().getFormatName().toUpperCase();
    }

    // should log if got error
    private static Map<String, Set<String>> getExtensionsMap() {
        Map<String, Set<String>> m = new TreeMap<String, Set<String>>();
        IIORegistry registry = IIORegistry.getDefaultInstance();
        Iterator<ImageReaderSpi> iter = registry.getServiceProviders(ImageReaderSpi.class, true);
        while (iter.hasNext()) {
            ImageReaderSpi spi = iter.next();
            try {
                String name = getFormatName(spi);
                Set<String> s = m.get(name);
                if (s == null) {
                    s = new HashSet<String>();
                    m.put(name, s);
                }
                for (String suffix : spi.getFileSuffixes()) {
                    s.add(suffix);
                }
            } catch (IOException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }
        return m;
    }

    public static FileFilter[] getFileFilters() {
        if (filters == null) {
            List<FileFilter> list = new ArrayList<FileFilter>();
            Map<String, Set<String>> m = getExtensionsMap();
            Set<String> allExtensions = new HashSet<String>();
            for (Object key: m.keySet()) {
                Set<String> extensions = m.get(key.toString());
                allExtensions.addAll(extensions);
                list.add(new ImgFileFilter(key + " Files", true, extensions));
            }
            list.add(0, new ImgFileFilter("Common Image files", false, allExtensions));
            filters = list.toArray(new FileFilter[0]);
        }
        return filters;
    }

    private FileTypeFilters() {
    }

    private static class ImgFileFilter extends FileFilter {

        private final String description;
        private final Set<String> extensions;

        ImgFileFilter(String name, boolean showExtensions, Set<String> extensions) {
            StringBuilder buf = new StringBuilder(name);
            if (showExtensions) {
                buf.append(" (");
                for (Iterator<String> iter = extensions.iterator(); iter.hasNext();) {
                    buf.append("*.").append(iter.next());
                    if (iter.hasNext())
                        buf.append(", ");
                }
                buf.append(')');
            }
            this.description = buf.toString();

            this.extensions = extensions;
        }

        public final boolean accept(File f) {
            String fileName = f.getPath().toLowerCase();
            boolean result = f.isDirectory();
            for (String ext: extensions) {
                result |= fileName.endsWith(ext);
            }
            return result;
        }

        public final String getDescription() {
            return description;
        }
    }
}
